const gulp            = require('gulp');
const del             = require('del');
const changed         = require('gulp-changed');
const sass            = require('gulp-sass');
const browserSync     = require('browser-sync');
const browserify      = require('browserify');
const watchify        = require('watchify');
const tsify           = require('tsify');
const pretty          = require('prettysize');
const merge           = require('lodash.merge');
const source          = require('vinyl-source-stream');
const buffer          = require('vinyl-buffer');
const sourcemaps      = require('gulp-sourcemaps');
const uglify          = require('gulp-uglify');
const stream          = require('stream');

const PATH = {
  src: 'app/' ,
  dest: 'dest/' ,
  html: {
    src: 'app/**/*.html' ,
    dest: 'dest/'
  } ,
  scss: {
    src: 'app/core.scss' ,
    files: 'app/**/*.scss' ,
    dest: 'dest/'
  } ,
  script: {
    src: 'app/**/*.ts'
  }
};

const OPTIONS = {
  src: ['./app/app.ts', './typings/index.d.ts'],
  outputPath: 'dest',
  outputFile: 'app.bundle.js',
  minify: false,
  browserifyOptions: {
    cache: {},
    packageCache: {},
    debug: true
  },
  watchifyOptions: {},
  tsifyOptions: {},
  uglifyOptions: {},
  onError: function(err){
    console.error(err.toString());
    this.emit('end');
  },
  onLog: function(log){
    console.log((log = log.split(' '), log[0] = pretty(log[0]), log.join(' ')));
  }
}

var src             = gulp.src;
var dest            = gulp.dest;
var argv            = process.argv;
var reload          = browserSync.reload;
var isRelease       = argv.indexOf('--release') > -1;
var bify            = watchify(browserify(OPTIONS.src,OPTIONS.browserifyOPTIONS).plugin(tsify,OPTIONS.tsifyOptions) ,OPTIONS.watchifyOptions)


gulp.task('default' ,['clean' ,'server' ,'watch']);

gulp.task('html' ,()=>{
  return src(PATH.html.src)
      .pipe(changed(PATH.html.dest))
      .pipe(dest(PATH.html.dest))
      .pipe(reload({stream:true}));
});

gulp.task('scss' ,()=>{
  return src(PATH.scss.src)
      .pipe(changed(PATH.scss.dest))
      .pipe(sass().on('error' ,sass.logError))
      .pipe(dest(PATH.scss.dest))
      .pipe(reload({stream: true}));
});

bify.on('update', ()=>{
  gulp.start('script');
}).on('log', OPTIONS.onLog);
gulp.task('script' ,()=>{
  return bify.bundle()
    .on('error', OPTIONS.onError)
    .pipe(source(OPTIONS.outputFile))
    .pipe(buffer())
    .pipe(OPTIONS.browserifyOptions.debug ? sourcemaps.init({ loadMaps: true }) : noop())
    .pipe(OPTIONS.minify ? uglify(OPTIONS.uglifyOptions) : noop())
    .pipe(OPTIONS.browserifyOptions.debug ? sourcemaps.write('./',{includeContent:true, sourceRoot:'../../../'}) : noop())
    .pipe(gulp.dest(OPTIONS.outputPath))
    .pipe(reload({stream: true}));
});

gulp.task('server' ,['html' ,'scss' ,'script'] ,()=>{
  browserSync.init({
    port: 8110 ,
    server: {
      baseDir: './'
    }
  });
});

gulp.task('watch' ,()=>{
  gulp.watch('index.html' ,reload);
  gulp.watch(PATH.html.src ,['html']);
  gulp.watch(PATH.scss.files ,['scss']);
  gulp.watch(PATH.script.src ,['script']);
});

gulp.task('clean' ,()=>{
  return del(PATH.dest+'/**/*');
});

function noop(){
  return new stream.PassThrough({ objectMode: true });
}
